<template>
	<div class="card filter">
		<h4 class="title sle" v-if="title">{{ title }}</h4>
		<slot name="toolButton" v-if="showToolBtn"></slot>
		<el-input v-model="filterText" placeholder="输入关键字进行过滤" clearable></el-input>
		<el-scrollbar
			:style="{
				height: title && showToolBtn ? `calc(100% - 120px)` : title || showToolBtn ? `calc(100% - 95px)` : `calc(100% - 56px)`
			}"
		>
			<el-tree
				ref="treeRef"
				:default-expand-all="defaultExpandAll"
				:node-key="id"
				:data="treeData"
				:show-checkbox="multiple"
				:check-strictly="multiple && checkStrictly"
				:current-node-key="!multiple ? selected : ''"
				:highlight-current="!multiple"
				:expand-on-click-node="expandOnClickNode"
				:props="defaultProps"
				:check-on-click-node="multiple"
				:filter-node-method="filterNode"
				:default-checked-keys="multiple ? selected : []"
				@node-click="handleNodeClick"
				@check="handleCheckChange"
			>
				<template #default="scope">
					<span class="el-tree-node__label">
						<slot :row="scope">
							{{ scope.node.label }}
						</slot>
					</span>
				</template>
			</el-tree>
		</el-scrollbar>
	</div>
</template>

<script lang="ts" setup name="TreeFilter">
import { ResultData } from "@/api/interface";
import { ElTree } from "element-plus";
import { nextTick, onBeforeMount, ref, watch } from "vue";
import { CirclePlus, Delete, EditPen, Download, Upload, View, Refresh } from "@element-plus/icons-vue";
// 接收父组件参数并设置默认值
interface TreeFilterProps {
	requestApi?: (data?: any) => Promise<ResultData>; // 请求分类数据的 api ==> 非必传
	initParam?: any; //初始化请求参数
	data?: { [key: string]: any }[]; // 分类数据，如果有分类数据，则不会执行 api 请求 ==> 非必传
	title?: string; // treeFilter标题 ==> 非必传
	id?: string; // 选择的id ==> 非必传， 默认为 "id"
	label?: string; // 显示的label ==> 非必传， 默认为 "label"
	parentId?: string; // 树节点f父id
	parentName?: string; // 树节点父name
	children?: string; // 子数据 ==> 非必传，默认为 "children"
	multiple?: boolean; // 是否为多选 ==> 非必传，默认为 false
	defaultValue?: any; // 默认选中的值 ==> 非必传
	checkStrictly?: boolean; // 在显示复选框的情况下，是否严格的遵循父子不互相关联的做法，默认为 false
	expandOnClickNode?: boolean; // 是否在点击节点的时候展开或者收缩节点， 默认值为 true，如果为 false，则只有点箭头图标的时候才会展开或者收缩节点。
	defaultExpandAll?: boolean; // 是否默认全部展开
	showToolBtn?: boolean; // 是否显示工具按钮
}

// 设置props默认值
const props = withDefaults(defineProps<TreeFilterProps>(), {
	id: "id",
	label: "label",
	children: "children",
	parentId: "",
	parentName: "",
	initParam: {},
	multiple: false,
	checkStrictly: false,
	expandOnClickNode: false,
	defaultExpandAll: true,
	showToolBtn: false
});

const defaultProps = {
	children: props.children,
	label: props.label
};

const treeRef = ref<InstanceType<typeof ElTree>>();
const treeData = ref<{ [key: string]: any }[]>([]);
// const treeAllData = ref<{ [key: string]: any }[]>([]);

const selected = ref();
const setSelected = () => {
	if (props.multiple) selected.value = Array.isArray(props.defaultValue) ? props.defaultValue : [props.defaultValue];
	else selected.value = props.defaultValue;
	// else selected.value = typeof props.defaultValue === "string" ? props.defaultValue : props.defaultValue;
};

onBeforeMount(async () => {
	setSelected();
	if (props.requestApi) {
		const { result } = await props.requestApi!(props.initParam);
		treeData.value = result;
		// treeAllData.value = [{ id: "", [props.label]: "全部" }, ...data];
	}
});

// 使用 nextTick 防止打包后赋值不生效，开发环境是正常的
watch(
	() => props.defaultValue,
	() => nextTick(() => setSelected()),
	{ deep: true, immediate: true }
);

watch(
	() => props.data,
	() => {
		if (props.data?.length) {
			treeData.value = props.data;
			// treeAllData.value = [{ id: "", [props.label]: "全部" }, ...props.data];
		}
	},
	{ deep: true, immediate: true }
);

const filterText = ref("");
watch(filterText, val => {
	treeRef.value!.filter(val);
});

// 过滤
const filterNode = (value: string, data: { [key: string]: any }, node: any) => {
	if (!value) return true;
	let parentNode = node.parent,
		labels = [node.label],
		level = 1;
	while (level < node.level) {
		labels = [...labels, parentNode.label];
		parentNode = parentNode.parent;
		level++;
	}
	return labels.some(label => label.indexOf(value) !== -1);
};

interface FilterEmits {
	(e: "change", value: any, label?: any, parentId?: any, parentName?: any): void;
}
const emit = defineEmits<FilterEmits>();

// 单选
const handleNodeClick = (data: { [key: string]: any }) => {
	console.log("sssssss: ", data, props, data[props.parentId], data[props.parentName]);
	if (props.multiple) return;
	if (data.disabled) return;
	emit("change", data[props.id], data[props.label], data[props.parentId], data[props.parentName]);
};

// 多选
const handleCheckChange = () => {
	emit("change", treeRef.value?.getCheckedKeys(), "");
};

// 暴露给父组件使用
defineExpose({ treeData, treeRef });
</script>

<style lang="scss" scoped>
.filter {
	box-sizing: border-box;
	width: 270px;
	height: 100%;
	padding: 18px;
	margin-right: 10px;
	.title {
		margin: 0 0 15px;
		font-size: 18px;
		font-weight: bold;
		color: var(--el-color-info-dark-2);
		letter-spacing: 0.5px;
	}
	.el-input {
		margin: 0 0 15px;
	}
	.el-scrollbar {
		:deep(.el-tree) {
			height: 80%;
			overflow: auto;
			.el-tree-node__content {
				height: 33px;
			}
		}
		:deep(.el-tree--highlight-current) {
			.el-tree-node.is-current > .el-tree-node__content {
				background-color: var(--el-color-primary);
				.el-tree-node__label,
				.el-tree-node__expand-icon {
					color: white;
				}
				.is-leaf {
					color: transparent;
				}
			}
		}
	}
}
</style>